package br.edu.fasete.javaroad.base;

import java.util.HashMap;
import java.util.List;

import br.edu.fasete.javaroad.log.LogManager;

import br.edu.fasete.javaroad.model.ClassDescriptor;
import br.edu.fasete.javaroad.model.EntityDescriptor;
import br.edu.fasete.javaroad.model.EntityList;
import br.edu.fasete.javaroad.model.InterfaceDescriptor;
import br.edu.fasete.javaroad.model.architeture.Component;
import br.edu.fasete.javaroad.model.architeture.VariableList;

public class GenericFileGenerator extends CodeGenerator {
	private Component component;
	private EntityList classes;
	private List<String> arquivos;
	private String diretorio;
	private HashMap<String, Object> variaveis;
	private String pacoteBase;	

	public GenericFileGenerator(String basePackage, EntityList classes, List<String> arquivos, VariableList parameters) {
		this.pacoteBase  = basePackage;
		this.classes = classes;
		this.arquivos = arquivos;
		variaveis = new HashMap<String, Object>();
		variaveis.put("package", this.getPacoteBase());
		variaveis.put("packageDir", this.getPacoteBase().replace(".", "/"));
		variaveis.put("classes", classes.getClasses());
		variaveis.put("parameters", parameters);
		variaveis.put("util", new Util());		
	}

	public void generateFileList(List<String> arquivos){
		if(component.isMultiple()) {
			generateMultipleFilesList(arquivos);
		} else {
			generateSingleFileList(arquivos);
		}
	}
	
	public void generate() {
		if(component.isMultiple()) {
			LogManager.getLogger().appendMessage("    Generation of multiple files");
			generateMultipleFiles();
		} else {
			LogManager.getLogger().appendMessage("    Generation of single files");
			generateSingleFile();
		}
	}

	private void generateMultipleFilesList(List<String> arquivos) {
		for(EntityDescriptor cd: classes.getClasses()) {
			if(cd.isDao() || !component.isOnlyDao()) {
				if( (cd instanceof ClassDescriptor && component.isUseClass()) || 
					(cd instanceof InterfaceDescriptor && component.isUseInterface()) )	
						
				arquivos.add(createFullFileName(cd.getName()));
			}
		}
	}
	
	private void generateSingleFileList(List<String> arquivos) {
		arquivos.add(createFullFileName(""));
	}
	
	private void generateMultipleFiles() {
		for(EntityDescriptor cd: classes.getClasses()) {
			if(cd.isDao() || !component.isOnlyDao()) {
				if((  cd instanceof ClassDescriptor && component.isUseClass()) ||
						cd instanceof InterfaceDescriptor && component.isUseInterface() ) {
					LogManager.getLogger().appendMessage("Generation of " + component.getName() + ": "+ cd.getName());
					gerarComponent(cd);
				}
			}
		}
	}

	private void generateSingleFile() {
		String arq = createFullFileName("");
		if(arquivos.contains(arq)) {
			LogManager.getLogger().appendMessage("           Creating File: " + arq);
			variaveis.remove("class");
			this.aplicarStringTemplate(component.getTemplate(),arq, variaveis);	
		}
	}

	private String createFullFileName(String file) {
		String arq = diretorio;
		if(!arq.endsWith("/"))
			arq+="/";
		arq+=file+component.getFilename();
		if(component.getFileExtension()!= null && !component.getFileExtension().equals("")) {
			if(!component.getFileExtension().startsWith("."))
				arq+=".";
			arq+=component.getFileExtension();
		}
		return arq;
	}

	private void gerarComponent(EntityDescriptor cls) {
		String arq = createFullFileName(cls.getName());
		if(arquivos.contains(arq)) {
			LogManager.getLogger().appendMessage("           Creating File: " + arq);
			variaveis.put("class", cls);
			this.aplicarStringTemplate(component.getTemplate(), arq, variaveis);
		}
	}

	public Component getComponent() {
		return component;
	}

	public void setComponent(Component component, String diretorio) {
		this.component = component;
		this.diretorio = diretorio;
		variaveis.put("component", component);
	}

	public List<String> getArquivos() {
		return arquivos;
	}

	public void setArquivos(List<String> arquivos) {
		this.arquivos = arquivos;
	}

	public String getPacoteBase() {
		return pacoteBase;
	}

	public void setPacoteBase(String pacoteBase) {
		this.pacoteBase = pacoteBase;
	}
}
